home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / prgmming / swag08 / exec.swg < prev    next >
Text File  |  1994-09-22  |  35KB  |  1 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00003                                                                           1      08-24-9413:36ALL                      DAVID ADAMSON            EXE Menu System          SWAG9408    ±Æk■    180    U   {πHere is a good scrolling menu bar program written in TP 5.5. Theπcode is very clean and well commented.π}ππprogram exemenu;                                      { version 2.2 }ππππ(****************************************** 1991 J.C. Kessels ****ππThis is freeware. No guarantees whatsoever. You may change it, use it,πcopy it, anything you like.πππJ.C. KesselsπPhilips de Goedelaan 7π5615 PN  EindhovenπNetherlandsπ********************************************************************)πππ{$M 3000,0,0}                     { No heap, or we can't use 'exec'. }πππuses dos;πππππconstπ(* English version: *)π  StrCopyright = 'EXEMENU v2.2, 1991 J.C. Kessels';{ Name of program. }π  StrBusy      = 'Busy....';                       { Program is busy message. }π  StrHelp      = 'Enter=Start  ESC=Stop';         { Bottom-left help message.}π  StrStart     = 'Busy starting program: ';        { Start a program message. }π  { Wrong DOS version message. }π  StrDos = 'Sorry, this program only works with DOS versions 3.xx and above.';π  { Unrecognised error message. }π  StrError     = 'EXEMENU: unrecognised error caused program termination.';π  StrExit      = 'That''s it, folks!';                   { Exit message. }π(* Dutch version: *)π(*π  StrCopyright = 'EXEMENU v2.2, 1991 J.C. Kessels';  { Naam van het programma.}π  StrHelp      = 'Enter=Start  ESC=Stop';       { Bodem-links hulp boodschap.}π  StrBusy      = 'Bezig....';                     { Ik ben bezig boodschap.}π  { Bij het starten van een programma. }π  StrStart     = 'Bezig met starten van: ';π  { Foutboodschap als de DOS versie niet goed is. }π  StrDos = 'Sorry, dit programma werkt slechts met DOS versie 3.xx en hoger.';π  { Onbekende fout boodschap. }π  StrError     = 'EXEMENU: door onbekende fout voortijdig beëindigd.';π  StrExit      = 'Exemenu is geëindigd.';        { Stop EXEMENU boodschap. }π*)ππ  DirMax = 1000;                    { Number of entries in directory array. }ππtypeπ  Str90 = string[90];             { We don't need anything longer than this. }ππvarπ  VidStore : array[0..3999] of char;                 { Video screen storage. }π  Dir : array[1..DirMax] of record  {The directory is loaded into this array.}π    attr : byte;                                     { 1: directory, 2: file.}π    name : NameStr;                              { Name of file/directory. }π    ext  : ExtStr;                                { Extension of file. }π    end;π  DirTop  : word;                        { Last active entry in Dir array. }π  DirHere : word;                       { Current selection in Dir array. }π  DirPath   : pathstr;                { The path of the Loaded directory. }π  OldPath   : PathStr;      { The current directory at startup of EXEMENU. }π  BasicPath : PathStr;                { The path to the basic interpreter. }π  OldCursor : word;                                  { Saved cursor shape. }π  xy     : word;                                  { Cursor on the screen. }π  colour : byte;                                 { Colour for the screen. }π  vidseg : word;                              { Segment of the screen RAM. }π  regs   : registers;                        { Registers to call the BIOS. }π  Inkey  : word;                                   { The last pressed key. }π  keyflags : byte absolute $0040:$0017;             { BIOS keyboard flags. }π  ExitSave : pointer;                         { Address of exit procedure. }π  ExitMsg  : Str90;                      { Message to display when exiting. }π  DTA  : SearchRec;                             { FindFirst-FindNext buffer. }ππfunction Left(s : Str90; width : byte) : Str90;π{Return Width characters from input string. Add trailing spaces if necessary.}πbeginπif width > length(s) then Fillchar(s[length(s)+1],width-length(s),32);πs[0] := chr(width);πLeft := s;πend;ππprocedure FixupDir;π{ Fixup the DirPath string. }πvarπ  drive : char;π  i, j : word;πbeginπi := pos(':',DirPath);                   { Strip the drive from the path. }πif i = 0 thenπ  beginπ  if (length(Dirpath) > 0) and (Dirpath[1] = '\')π    then DirPath := copy(OldPath,1,2) + DirPathπ    else if OldPath[length(OldPath)] = '\'π      then DirPath := OldPath + DirPathπ      else DirPath := OldPath + '\' + DirPath;π  i := pos(':',DirPath);π  end;πdrive := DirPath[1];πdelete(DirPath,1,i);ππwhile pos('..',DirPath) <> 0 do                    { Remove embedded ".." }π  beginπ  i := pos('..',DirPath);π  j := i + 2;π  if i > 1 then dec(i);π  if (i > 1) and (DirPath[i] = '\') then dec(i);π  while (i > 1) and (DirPath[i] <> '\') do dec(i);π  delete(DirPath,i,j-i);π  end;ππ{ Remove embedded ".\" }πwhile pos('.\',DirPath) <> 0 do delete(DirPath,pos('.\',DirPath),2);ππif pos('\',DirPath) = 0                        { If no subdirectories.... }π  then DirPath := '\'π  elseπ    begin                          { Else strip filename from the path.... }π    i := pos('.',DirPath);π    if i > 0 thenπ      beginπ      while (i > 0) and (DirPath[i] <> '\') do dec(i);π      if i > 0π        then DirPath := copy(DirPath,1,i)π        else DirPath := '\';π      end;π    if DirPath[length(DirPath)] <> '\'       { maybe add '\' at the end.... }π      then DirPath := DirPath + '\';π    end;ππDirPath := drive + ':' + DirPath;    { Add the drive back to the directory. }ππ{ Translate the Dirpath into all uppercase. }πfor i := 1 to length(DirPath) do DirPath[i] := upcase(DirPath[i]);πend;ππprocedure Show(s : Str90);π{ Display string "s" at "xy", using "colour". This routine uses DMA into theπ  video memory. }πbeginπInline(π  $8E/$06/>VIDSEG/       {mov  es,[>vidseg]   ; Fetch video segment in ES.}π  $8B/$3E/>XY/           {mov  di,[>xy]       ; Fetch video offset in DI.}π  $8A/$26/>COLOUR/       {mov  ah,[>colour]   ; Fetch video colour in AH.}π  $1E/                   {push ds             ; Setup DS to stack segment.}π  $8C/$D1/               {mov  cx,ss}π  $8E/$D9/               {mov  ds,cx}π  $8A/$8E/>S/            {mov  cl,[bp+>s]     ; Fetch string size in CX.}π  $30/$ED/               {xor  ch,ch}π  $8D/$B6/>S+1/          {lea  si,[bp+>s+1]   ; Fetch string address in SI.}π  $E3/$04/               {jcxz l2             ; Skip if zero length.}π                         {l1:}π  $AC/                   {lodsb               ; Fetch character from string.}π  $AB/                   {stosw               ; Show character.}π  $E2/$FC/               {loop l1             ; Next character.}π                         {l2:}π  $1F/                   {pop  ds             ; Restore DS.}π  $89/$3E/>XY);          {mov  [>xy],di       ; Store new XY.}πend;ππprocedure ShowMenu(Message : Str90);π{ Display the screen, with borders, a "Message" in line 2, and the loadedπ  directory in the rest of the screen. }πvarπ  i   : word;                         { Work variable. }π  s   : Str90;                        { Work variable. }π  pagetop : word;                     { Top of the page in the Dir array. }π  row     : word;                     { The display row we are busy with. }πbeginπxy := 0;                               { First line. }πcolour := $13;πif length(StrCopyright) > 76π  then i := 76π  else i := length(StrCopyright);πs[0] := chr((76 - i) div 2);πFillchar(s[1],ord(s[0]),'═');πShow('╔'+s+'╡');πcolour := $1B;πShow(copy(StrCopyright,1,i));πcolour := $13;πs[0] := chr(76 - length(s) - length(StrCopyright));πFillchar(s[1],ord(s[0]),'═');πShow('╞'+s+'╗║ ');ππcolour := $1E;                                 { Second line. }πShow(left(Message,76));ππcolour := $13;                                   { Third line. }πShow(' ║╟──────────────────────────────────────────────────────────────────────────────╢');ππ{ Display all the directory entries, using the current cursor positionπ  to calculate the top-left of the page. }πpagetop := DirHere - DirHere mod 105 + 1;πfor i := pagetop to pagetop + 20 doπ  beginπ  colour := $13;π  Show('║ ');π  colour := $1E;π  row := 0;π  while row <= 84 doπ    beginπ    if i+row <= DirTopπ      then if Dir[i+row].attr = 1π        then Show(left(Dir[i+row].name,14))π        else Show(left(Dir[i+row].name,8) + '.' + left(Dir[i+row].ext,5))π      else Show('              ');π    row := row + 21;π    end;π  colour := $13;π  Show('       ║');π  end;ππcolour := $13;                                      { Last line. }πShow('╚══╡');πcolour := $1B;πif length(StrHelp) > 74π  then i := 74π  else i := length(StrHelp);πShow(copy(StrHelp,1,i));πcolour := $13;πs[0] := chr(74-i);πFillchar(s[1],ord(s[0]),'═');πShow('╞'+s+'╝');πend;ππprocedure ShowBar(here : word; onoff : boolean);π{ Display (onoff = true) or remove (onoff = false) the cursor bar at the screenπ  location that shows the "here" entry in the Dir array. Every entry has aπ  fixed location on the screen. }πvarπ  i : word;πbeginπi := Here mod 105 - 1;                { Calculate position on screen. }πxy := 484 + (i div 21) * 28 + (i mod 21) * 160;πif onoff                              { Setup the proper colour. }π  then colour := $70π  else colour := $1E;πif Here <= DirTop                     { Display the Dir entry. }π  then if Dir[Here].attr = 1π    then Show(left(Dir[Here].name,12))  { Directories without a dot. }π    else Show(left(Dir[Here].name,8) + '.' + left(Dir[Here].ext,3))π  else Show('            ');              { Empty entries. }πcolour := $1E;                            { Reset the colour. }πend;ππprocedure InitVideo;π{ Initialise the video. If not 80x25 then switch to it. Store the screen.π  Hide the cursor. }πvarπ  i : byte;πbeginπregs.ah := $0F;            { If not text mode 3 or 7, then switch to it. }πintr($10,regs);πi := regs.al and $7F;πregs.ah := $03;            { Save current cursor shape. BH is active page. }πintr($10,regs);πOldCursor := regs.cx;πif (i <> 3) and (i <> 7) thenπ  beginπ  regs.al := 3;π  regs.ah := 0;π  intr($10,regs);π  i := 3;π  end;ππif i <> 7                          { Compute video segment. }π  then vidseg := $B800 + (memw[$0040:$004E] shr 4)π  else vidseg := $B000 + (memw[$0040:$004E] shr 4);ππmove(mem[vidseg:0],VidStore[0],4000);   { Store current screen. }ππregs.cx := $2000;                        { Hide cursor. }πregs.ah := 1;πintr($10,regs);ππcolour := $1E;                             { Reset attribute. }πxy := 0;                                   { Reset cursor. }πend;ππprocedure ResetVideo;π{ Reset the video back to it's original contents. Show the cursor. }πbeginπmove(VidStore[0],mem[vidseg:0],4000);       { Restore screen. }ππregs.cx := OldCursor;                       { Reset original cursor chape. }πregs.ah := 1;πintr($10,regs);πend;ππ{$F+}πprocedure ExitCode;π{ Reset display upon exit. This also works for error exit's. }πbeginπResetVideo;                           { Reset the original display contents. }πif ExitMsg <> '' then writeln(ExitMsg);    { Show exit message. }πChDir(OldPath);                            { Restore current path. }πExitProc := ExitSave;        { Reset previous exit procedure. }πend;π{$F-}ππprocedure LoadDir;π{ Load the "DirPath" directory into memory. }πvarπ  i    : word;                                  { Work variable. }π  s    : pathstr;                               { Work variable. }π  name : NameStr;                               { Name of current file. }π  ext  : ExtStr;                                { Extension of current file. }π  attr : byte;                                  { Attribute of current file. }πbeginπcolour := $1E;                                  { Show "busy" message. }πxy := 164;πShow(left(StrBusy,76));ππFixupDir;                               { Cleanup the DirPath string. }πDirTop := 0;                            { Reset pointers into the Dir array.}πDirHere := 1;ππFindFirst(DirPath+'*.*',AnyFile,DTA);                 { Find first file. }πwhile (DosError = 3) and (length(DirPath) > 3) do     { If path not found....}π  beginπ  i := length(DirPath);             { then strip last directory from path. }π  if i > 3 then dec(i);π  while (i > 3) and (DirPath[i] <> '\') do dec(i);π  DirPath := copy(DirPath,1,i);π  FindFirst(DirPath+'*.*',AnyFile,DTA);                 { And try again. }π  end;ππwhile DosError = 0 do                                { For all the files. }π  beginπ  attr := 0;π  if (DTA.attr and Directory) = Directoryπ    thenπ      begin                                      { Setup for directories. }π      name := DTA.name;π      ext := '';π      if DTA.name <> '.' then attr := 1;          { Ignore '.' directory. }π      if DTA.name = '..' then name := '..';π      endπ    elseπ      beginπ      for i := 1 to length(DTA.name) do  { Translate filename to lowercase. }π        if DTA.name[i] IN ['A'..'Z'] thenπ          DTA.name[i] := chr(ord(DTA.name[i])+32);π      i := pos('.',DTA.name);       { Split filename in name and extension. }π      if i > 0π        thenπ          beginπ          name := copy(DTA.name,1,i-1);π          ext  := copy(DTA.name,i+1,length(DTA.name)-i);π          endπ        elseπ          beginπ          name := DTA.name;π          ext := '';π          end;π      { Ignore unrecognised extensions. }π      if (ext = 'com') and (DTA.name <> 'command.com') then attr := 2;π      if (ext = 'exe') and (DTA.name <> 'exemenu.exe') then attr := 2;π      if (ext = 'bat') and (DTA.name <> 'autoexec.bat') then attr := 2;π      if (ext = 'bas') and (BasicPath <> '') then attr := 2;π      end;π  { If recognised extension or directory, then load into memory. }π  if attr > 0 thenπ    beginπ    i := 1;π    while (i <= DirTop) and         { Find location where to insert (sort). }π      ((attr > Dir[i].attr) orπ      ((attr = Dir[i].attr) and (name > Dir[i].name)) orπ      ((attr = Dir[i].attr) and (name = Dir[i].name) and (ext > Dir[i].ext)))π      do inc(i);π    if DirTop < DirMax then inc(DirTop);π    if i < DirTop then              { Move entries up, to create entry. }π      move(Dir[i],Dir[i+1],sizeof(Dir[1]) * (DirTop - i));π    if i <= DirMax then              { Fill the entry. }π      beginπ      Dir[i].name := name;π      Dir[i].ext  := ext;π      Dir[i].attr := attr;π      end;π    end;π  FindNext(DTA);                           { Next item. }π  end;ππ{ Analyse the results. If nothing found (maybe disk error), and if we are in aπ  subdirectory, then at least add the parent directory. }πif (DirTop = 0) and (length(DirPath) > 3) thenπ  beginπ  Dir[1].name := '..';π  Dir[1].ext  := '';π  Dir[1].attr := 1;π  DirTop      := 1;π  end;ππend;ππprocedure ExecuteProgram;π{ Execute the program at "DirHere". }πvarπ  ProgramPath : pathstr;               { Path to the program to execute. }πbeginπ{ Return from this subroutine if there is no program at the cursor. }πif (DirHere < 1) or (DirHere > DirTop) or (Dir[DirHere].attr <> 2) then exit;ππcolour := $1E;                           { Show "busy" message. }πxy := 164;πShow(left(StrBusy,76));ππ{ Setup path to the program. }πProgramPath := DirPath + Dir[DirHere].name + '.' + Dir[DirHere].ext;ππFindFirst(ProgramPath,AnyFile,DTA); { Test if the path to the program exists. }πif DosError <> 0 then exit;                       { Exit if error. }πResetVideo;                                       { Reset the video screen. }πwriteln(StrStart,ProgramPath);                    { Show startup message. }ππChDir(copy(DirPath,1,length(DirPath)-1));        { Change to the directory. }πSwapVectors;                                     { Start program. }πif Dir[DirHere].ext = 'bat'            { .BAT files trough the COMMAND.COM. }π  then Exec(getenv('COMSPEC'),'/C '+ProgramPath)π  else if Dir[DirHere].ext = 'bas'     { .BAS trough the basic interpreter. }π    then Exec(BasicPath,ProgramPath)π    else Exec(ProgramPath,'');                { Others directly. }πSwapVectors;ππInitVideo;                                    { Initialise the video. }πShowMenu(StrBusy);                     { Draw screen with "busy" message. }ππ{ Reset keyboard flags. }πkeyflags := keyflags and $0F;  {Capslock, Numlock, ScrollLock and Insert off.}πfillchar(regs,sizeof(regs),#0);                   { Clear registers. }πregs.ah := 1;                                     { Activate new setting. }πintr($16,regs);ππregs.ah := 1;                                    { Clear the keyboard buffer.}πintr($16,regs);πwhile (regs.flags and fzero) = 0 doπ  beginπ  regs.ah := 0;π  intr($16,regs);π  regs.ah := 1;π  intr($16,regs);π  end;ππInkey := 13;πend;ππvarπ  i : word;                                            { Workvariable. }π  s : Str90;                                           { Workvariable. }π  OldHere, OldPageTop : word;         { Determine if cursor has moved. }ππbeginπDirPath := '';                         { No directory loaded right now. }πDirTop := 0;                           { No directory loaded right now. }πExitMsg := StrError;                   { Reset error message. }πgetdir(0,OldPath);                     { Save current directory. }πExitSave := ExitProc;                  { Setup exit procedure. }πExitProc := @ExitCode;πInitVideo;                             { Initialise the video. }πShowMenu(StrBusy);                     { Draw screen with "busy" message. }ππif lo(DosVersion) < 3 then             { Test DOS version. }π  beginπ  ExitMsg := StrDos;π  halt(1);π  end;ππ{ Determine what directory to search for programs. Default is the currentπ  directory. Otherwise the first argument after EXEMENU is used as startingπ  path. }πif paramcount = 0π  then DirPath := OldPathπ  else DirPath := paramstr(1);ππ{ Find the basic interpreter somewhere in the path. If not found, then basicπ  programs will not be listed. }πBasicPath := Fsearch('GWBASIC.EXE',GetEnv('PATH'));πif BasicPath = '' then BasicPath := Fsearch('GWBASIC.COM',GetEnv('PATH'));πif BasicPath = '' then BasicPath := Fsearch('BASIC.EXE',GetEnv('PATH'));πif BasicPath = '' then BasicPath := Fsearch('BASIC.COM',GetEnv('PATH'));πif BasicPath = '' then BasicPath := Fsearch('BASICA.EXE',GetEnv('PATH'));πif BasicPath = '' then BasicPath := Fsearch('BASICA.COM',GetEnv('PATH'));πif BasicPath <> '' then BasicPath := FExpand(BasicPath);ππLoadDir;                               { Load the directory into memory. }πShowMenu(DirPath);                     { Display the directory. }πShowBar(DirHere,true);                 { Highlight the current choice. }ππ{ The main loop, exited only when the user presses ESC. }πrepeatπ  { Wait for a key to be pressed. Place the scancode in the Inkey variable. }π  regs.ah := 0;π  intr($16,regs);π  Inkey := regs.ax;ππ  if lo(Inkey) = 13 then               { Process ENTER key. }π    beginπ    ShowBar(DirHere,false);            { Remove cursor bar. }π    s := '';                           { No item stored. }π    { If cursor points to a program....}π    if DirHere <= DirTop then if Dir[DirHere].attr = 2π      thenπ        beginπ        { Store the item to execute, so we can move the cursor back to it. }π        s := Dir[DirHere].name + '.' + Dir[DirHere].ext;π        ExecuteProgram;                { Then execute the program....}π        endπ      else if Dir[DirHere].name <> '..'   { Else goto the directory....}π        then DirPath := fexpand(DirPath+Dir[DirHere].name) + '\'π        elseπ          begin                           { Or goto the parent directory. }π          i := length(DirPath) - 1;π          while (i >= 1) and (DirPath[i] <> '\') do dec(i);π          {Store the directory we just left, so we can move the cursor to it.}π          s := copy(DirPath,i+1,length(DirPath)-i-1);π          if i > 0π            then DirPath := copy(DirPath,1,i)π            else DirPath := '\';π          end;π    LoadDir;                              { Reload the directory. }π    { If an item was stored, then find it, and move the cursor to it. }π    if s <> '' thenπ      beginπ      DirHere := 1;π      if pos('.',s) = 0π        then while (DirHere < DirTop) and (Dir[DirHere].name <> s) doπ          inc(DirHere)π        else while (DirHere < DirTop) andπ          (Dir[DirHere].name + '.' + Dir[DirHere].ext <> s) do inc(DirHere);π      if (DirHere <= DirTop) and (π          ((pos('.',s) = 0) andπ           (Dir[DirHere].name <> s)) orπ          ((pos('.',s) > 0) andπ           (Dir[DirHere].name + '.' + Dir[DirHere].ext <> s)) )π        then DirHere := 1;π      end;π    ShowMenu(DirPath);                    { Show the menu. }π    ShowBar(DirHere,true);                { Show cursor bar. }π    end;ππ  { Process cursor movement keys. }π  OldHere := DirHere; {Remember current cursor, to determine if it has moved.}π  if (Inkey = $4800) and (DirHere > 1) then dec(DirHere);        { arrow-up.}π  if (Inkey = $5000) and (DirHere < DirTop) then inc(DirHere);   {arrow-down.}π  if (Inkey = $4D00) or (lo(Inkey) = 9) then             {arrow-right or tab.}π    if DirHere + 21 <= DirTopπ      then DirHere := DirHere + 21π      else DirHere := DirTop;π  if (Inkey = $4B00) or (Inkey = $0F00) then    { arrow-left or shift-tab. }π    if DirHere > 21π      then DirHere := DirHere - 21π      else DirHere := 1;π  if (Inkey = $5100) and (DirHere < DirTop) then                   { pgdn. }π    if DirTop > 105π      then if DirHere + 105 < DirTopπ        then DirHere := DirHere + 105π        else DirHere := DirTopπ      else if (DirHere - 1) mod 21 = 20π        then if DirHere + 21 <= DirTopπ          then DirHere := DirHere + 21π          else DirHere := DirTopπ        else if DirHere - (DirHere - 1) mod 21 + 20 < DirTopπ          then DirHere := DirHere - (DirHere - 1) mod 21 + 20π          else DirHere := DirTop;π  if (Inkey = $4900) and (DirHere > 1) then                        { pgup. }π    if DirTop > 105π      then if DirHere > 105π        then DirHere := DirHere - 105π        else DirHere := 1π      else if (DirHere - 1) mod 21 = 0π        then if DirHere > 21π          then DirHere := DirHere - 21π          else DirHere := 1π        else DirHere := DirHere - (DirHere - 1) mod 21;π  if Inkey = $4700 then DirHere := 1;                             { home. }π  if Inkey = $4F00 then DirHere := DirTop;                         { end. }π  if lo(Inkey) > 31 then                      {Process a character inkey. }π    beginπ    i := 1;π    while (i <= DirTop) and (Dir[i].name[1] <> chr(lo(Inkey))) do inc(i);π    if i <= DirTop then DirHere := i;π    end;π  if DirHere = 0 then DirHere := 1;           { Correct for empty list. }π  { If the cursor has moved off the screen, then redraw the menu. }π  if OldHere - OldHere mod 105 + 1 <> DirHere - DirHere mod 105 + 1 thenπ    beginπ    ShowBar(OldHere,false);π    ShowMenu(DirPath);π    ShowBar(DirHere,true);π    OldHere := DirHere;π    end;π  if OldHere <> DirHere then    { If the cursor has moved, then redraw it. }π    beginπ    ShowBar(OldHere,false);π    ShowBar(DirHere,true);π    end;ππuntil lo(Inkey) = 27;                             { Until ESC key pressed. }ππExitMsg := StrExit;                                   { Exit with message. }πend.π                                                                                          2      08-24-9413:45ALL                      FRANK DIACHEYSN          Multiple DOS Calls       SWAG9408    ,t╪    11     U   {π  Coded By Frank Diacheysn Of Gemini Softwareππ  FUNCTION MASSEXECππ  Input......: DOS Command Line(s)π             :π             :π             :π             :ππ  Output.....: Logicalπ             :        TRUE  = No Errors During Executionπ             :        FALSE = Error Occured During Executionπ             :π             :ππ  Example....: IF MASSEXEC('DIR,PAUSE') THENπ             :   WriteLn('No Errors!')π             : ELSEπ             :   WriteLn('DOS Error Occured!');π             :ππ  Description: Execute One Or More DOS Program Callsπ             : (Seperate Calls With A Comma)π             :π             :π             :ππ}πFUNCTION MASSEXEC( S:STRING ):BOOLEAN;π{$M $4000,0,0}πVAR nCount : INTEGER;πVAR ExS    : STRING;πVAR Ch     : CHAR;πBEGINπ  REPEATπ    nCount := 0;π    ExS := '';π    REPEATπ      Inc(nCount);π      Ch := S[nCount];π      IF Ch <> ',' THENπ        ExS := ExS + Ch;π    UNTIL (Ch = ',') OR (nCount = Length(S));π    IF POS(',',S)=0 THENπ      S := ''π    ELSEπ      DELETE(S,1,POS(',',S));π    SWAPVECTORS;π    EXEC( GETENV('COMSPEC'), '/C '+ ExS );π    SWAPVECTORS;π    MASSEXEC := DOSERROR = 0;π  UNTIL S = '';πEND;π                                                                                                               3      08-24-9413:47ALL                      MIKE PERRY               Menu System              SWAG9408    2Lm╖    83     U   {π GG> Could somebody post a message with the Pascal 6.0 source for someπ GG> sort of a scrolling menu system?  I do NOT want TurboVision.  Iπ GG> HATE OOP.  I don't mind records and arrays, but i don't want OOP.π GG> I've done some programming for one myself....π}ππUNIT MPMENU;π{π Written and designed by Michael Perry, (c) 1990 Progressive Computer Serv.ππ A basic, flexible, user-definable menu system using only the most basicπ functions in Turbo Pascal.  This unit is easily integratable into yourπ applications and gives you more versatility than most "pull down"-typeπ menu interfaces.ππ License:  This unit should NOT be modified and redistributed in sourceπ           or object/TPU form.  You can modify and use this in any non-π           commercial program free-of-charge provided that "Mike Perry"π           if credited either in the program or documentation.  Use ofπ           these routines in a commercially-sold package requires aπ           one-time registration fee of $30 to be sent to:ππ             Progressive Computer Servicesπ             P.O. Box 7638π             Metairie, LA 70010ππ           Non-commercial users are also invited to register the code.π           This insures that updates and future revisions are madeπ           available and users are kept informed via mail.πππ Usage:    Implementing menus using the MPMENU unit involves just aπ           few basic steps.  At any point in your program, add codeπ           to perform the following actions:ππ              1.  Define the menu by assigning values to the MENU_DATAπ                  record.π              2.  Call the procedure MENU(MENU_DATA,RETURNCODE);π              3.  Implement a routine to evaluate the value ofπ                  RETURNCODE and act accordingly.  The values ofπ                  RETURNCODE are as follows:π                    0   = ESC pressed (menu aborted)π                    1-x = The appropriate option was selected, with 1π                          being the first menu choice, 2 the second,π                          etc.ππ Example:  Here is a sample main menu using the MENU procedure:π-----------------------------------------------------------------------------π   Program DontDoMuch;π   Uses Crt,MPMenu;ππ   CONST     HELL_FREEZES_OVER=FALSE;π   VAR       CHOICE:BYTE;ππ   Beginπ     REPEATππ     With Menu_Data Do Beginπ       Menu_Choices[1]:='1 - First Option ';    - define menu choice onscreenπ       Row[1]:=10; Column[1]:=30;               - where on screen displayedπ       Menu_Choices[2]:='2 - Second Option';    - same thing for 2nd choiceπ       Row[2]:=12; Column[2]:=30;                 .π       Menu_Choices[3]:='X - Exit Program ';      .π       Row[3]:=14; Column[3]:=30;                 .π       Onekey:=TRUE;                            - enable 1-key executionπ       Num_Choices:=3;                          - number of menu choicesπ       HiLighted:=112;                          - highlighted attributeπ       Normal:=7;                               - normal attributeπ     End;ππ     MENU(MENU_DATA,CHOICE);          - call the menu now and wait for userππ     Case Choice Of                   - evaluate user response and actπ       0:Halt;                        - ESC pressedπ       3:Halt;                        - option 3, Exit, selectedπ       1:Beginπ           - put code here to do menu option 1π         End;π       2:Beginπ           - put code here to do menu option 2π         End;π     Endππ     UNTIL HELL_FREEZES_OVER;          - infinite loop - back to main menuπEnd.π-----------------------------------------------------------------------------π}πINTERFACEππ  USES Crt;ππ  CONSTπ    MAX_CHOICES = 10;                            { MAX_CHOICES can be changedπ                                                   depending upon the highestπ                                                   number of options you willπ                                                   have on any given menu }ππ  TYPEπ    MENU_ARRAY = RECORD                          { record structure for menu }π      MENU_CHOICES : ARRAY[1..MAX_CHOICES] OF STRING[50];  { displayed option }π      COLUMN       : ARRAY[1..MAX_CHOICES] OF BYTE;        { column location }π      ROW          : ARRAY[1..MAX_CHOICES] OF BYTE;  { row location }π      NUM_CHOICES  : BYTE;                           { # choices on menu }π      HILIGHTED    : WORD;                           { attribute for hilight }π      NORMAL       : WORD;                           { attributed for normal }π      ONEKEY       : BOOLEAN;                        { TRUE for 1-key executionπ}π    END;ππ  VARπ    MENU_DATA : MENU_ARRAY;                      { global menu variable }ππ{π  NOTE:  You can define many menu variables simultaneously, but since youπ         can generally use only one menu at a time, you can conserveπ         memory and program space by re-defining this one MENU_DATA recordπ         each time a menu is to be displayed.π}ππ{ internal procedures }π  PROCEDURE SHOW_MENU(MENU_DATA:MENU_ARRAY);π  PROCEDURE HILIGHT_CHOICE(MENU_DATA:MENU_ARRAY;CHOICENUM:BYTE);π  PROCEDURE UNHILIGHT_CHOICE(MENU_DATA:MENU_ARRAY;CHOICENUM:BYTE);π  FUNCTION GETKEY(VAR FUNCTIONKEY:BOOLEAN):CHAR;π  FUNCTION FOUND_CHOICE(MENU_DATA:MENU_ARRAY;VAR EXITCODE:BYTE;CH:CHAR):BOOLEAN;ππ{ basically, the ONE callable procedure }π  PROCEDURE MENU(MENU_DATA:MENU_ARRAY;VAR EXITCODE:BYTE);ππIMPLEMENTATIONπππ(*===========================================================================*)πPROCEDURE SHOW_MENU(MENU_DATA:MENU_ARRAY);π{ display defined menu array }πVAR I:BYTE;πBEGINπ  TEXTATTR:=MENU_DATA.NORMAL;π  FOR I:=0 TO (MENU_DATA.NUM_CHOICES-1) DO BEGINπ    GOTOXY(MENU_DATA.COLUMN[I+1],MENU_DATA.ROW[I+1]);π    WRITE(MENU_DATA.MENU_CHOICES[I+1]);π  END;πEND;π(*===========================================================================*)πPROCEDURE HILIGHT_CHOICE(MENU_DATA:MENU_ARRAY;CHOICENUM:BYTE);π{ highlight the appropriate menu choice }πBEGINπ  GOTOXY(MENU_DATA.COLUMN[CHOICENUM],MENU_DATA.ROW[CHOICENUM]);π  TEXTATTR:=MENU_DATA.HILIGHTED;π  WRITE(MENU_DATA.MENU_CHOICES[CHOICENUM]);π  { below needed if direct screen writing not done }π  GOTOXY(MENU_DATA.COLUMN[CHOICENUM],MENU_DATA.ROW[CHOICENUM]);πEND;π(*===========================================================================*)πPROCEDURE UNHILIGHT_CHOICE(MENU_DATA:MENU_ARRAY;CHOICENUM:BYTE);π{ highlight the appropriate menu choice }πBEGINπ  GOTOXY(MENU_DATA.COLUMN[CHOICENUM],MENU_DATA.ROW[CHOICENUM]);π  TEXTATTR:=MENU_DATA.NORMAL;π  WRITE(MENU_DATA.MENU_CHOICES[CHOICENUM]);πEND;π(*===========================================================================*)πFUNCTION GETKEY(VAR FUNCTIONKEY:BOOLEAN):CHAR;π{ read keyboard and return character/function key }πVAR CH: CHAR;πBEGINπ  CH:=ReadKey;π  IF (CH=#0) THENπ    BEGINπ      CH:=ReadKey;π      FUNCTIONKEY:=TRUE;π    ENDπ  ELSE FUNCTIONKEY:=FALSE;π  GETKEY:=CH;πEND;π(*===========================================================================*)πFUNCTION FOUND_CHOICE(MENU_DATA:MENU_ARRAY;VAR EXITCODE:BYTE;CH:CHAR):BOOLEAN;π{ locate next occurance of menu choice starting with char CH }πVAR I:BYTE; TEMP:STRING;πBEGINπ  CH:=UPCASE(CH);π  IF EXITCODE=MENU_DATA.NUM_CHOICES THEN BEGINπ    TEMP:=MENU_DATA.MENU_CHOICES[1];π    IF UPCASE(TEMP[1])=CH THEN BEGINπ      UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π      EXITCODE:=1;π      HILIGHT_CHOICE(MENU_DATA,EXITCODE);π      FOUND_CHOICE:=TRUE;π      EXIT;π    END;π  END;ππ  FOR I:=EXITCODE+1 TO MENU_DATA.NUM_CHOICES DO BEGINπ    TEMP:=MENU_DATA.MENU_CHOICES[I];π    IF UPCASE(TEMP[1])=CH THEN BEGINπ      UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π      EXITCODE:=I;π      HILIGHT_CHOICE(MENU_DATA,EXITCODE);π      FOUND_CHOICE:=TRUE;π      EXIT;π    END;π  END;ππ  IF EXITCODE<>1 THEN BEGIN             { KILLER RECURSION }π    UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π    EXITCODE:=1;π    IF FOUND_CHOICE(MENU_DATA,EXITCODE,CH) THEN BEGINπ      HILIGHT_CHOICE(MENU_DATA,EXITCODE);π      FOUND_CHOICE:=TRUE;π      EXIT;π    END ELSE HILIGHT_CHOICE(MENU_DATA,EXITCODE);π  END ELSE BEGINπ    TEMP:=MENU_DATA.MENU_CHOICES[1];π    IF UPCASE(TEMP[1])=CH THEN BEGINπ      FOUND_CHOICE:=TRUE;π      EXIT;π    END;π  END;π  FOUND_CHOICE:=FALSE;πEND;π(*===========================================================================*)πPROCEDURE MENU(MENU_DATA:MENU_ARRAY;VAR EXITCODE:BYTE);π{ display menu and return user's response:π   0   = ESC pressedπ   1-x = appropriate choice selectedππ   during operation, variable EXITCODE holds number of currently-selectedπ   menu choice.π}πVARπ  FNC:BOOLEAN; TEMPATTR:WORD;π  CH:CHAR;πBEGINπ  TEMPATTR:=TEXTATTR;π  IF (EXITCODE=0) OR (EXITCODE>MENU_DATA.NUM_CHOICES) THENπ    EXITCODE:=1;π  SHOW_MENU(MENU_DATA);π  HILIGHT_CHOICE(MENU_DATA,EXITCODE);π  REPEATπ    CH:=GETKEY(FNC);π    IF FNC THEN BEGINπ      IF CH=#77 THEN CH:=#80 ELSEπ      IF CH=#75 THEN CH:=#72;ππ      CASE CH OFπ        #72:IF EXITCODE>1 THEN BEGIN                              { UP }π              UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π              EXITCODE:=EXITCODE-1;π            END;π        #80:IF EXITCODE<MENU_DATA.NUM_CHOICES THEN BEGIN          { DOWN }π              UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π              EXITCODE:=EXITCODE+1;π            END;π        #71:IF EXITCODE<>1 THEN BEGIN                             { HOME }π              UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π              EXITCODE:=1;π            END;π        #79:IF EXITCODE<MENU_DATA.NUM_CHOICES THEN BEGIN          { END }π              UNHILIGHT_CHOICE(MENU_DATA,EXITCODE);π              EXITCODE:=MENU_DATA.NUM_CHOICES;π            END;π      END; { functionkey CASE }π      HILIGHT_CHOICE(MENU_DATA,EXITCODE);π    END { if FNC }ππ    ELSEπ      CASE CH OFπ        #27:BEGINπ              EXITCODE:=0;π              TEXTATTR:=TEMPATTR;π              EXIT;π            END;π        #13:BEGINπ              TEXTATTR:=TEMPATTR;π              EXIT;π            END;π      ELSEπ        IF FOUND_CHOICE(MENU_DATA,EXITCODE,CH) THENπ          IF (MENU_DATA.ONEKEY) THEN BEGINπ            TEXTATTR:=TEMPATTR;π            EXIT;π          END ELSE { nothing }π        ELSEπ{          BEGINπ            GOTOXY(1,20);  used for debuggingπ            WRITELN('FNC=',FNC,'      KEYVAL=',ORD(CH));π          END;π }π      END; {case}π  UNTIL FALSE;πEND;π(*===========================================================================*)πEND. { of unit MPMENU }ππ